/**
 * @file ActorManager.hpp
 *
 * @date 06/02/2012
 * @author Tales 
 *
 */

#ifndef ACTORMANAGER_HPP_
#define ACTORMANAGER_HPP_

#include "LayerManager.hpp"
#include <list>
#include "common.hpp"
#include <map>
#include "ActorHandlers.hpp"

namespace wolf {
using namespace std;

/**
 * @brief Class that handles the events targeted to Actors.
 * @ingroup actorsMod
 *
 *
 * It has a general behavior that can be modified or just used.
 * If you want to modify (like to add some new event type) you
 * just extend this class and create a instance before any actor
 * creation (if some actor exists before, it may show undefined
 * behavior).
 */
class WOLF_DECLSPEC ActorManager: public LayerManager {
public:
	/**
	 * @brief a simple destructor.
	 */
	virtual ~ActorManager();

	void onSetup(Engine &engine);
	void onCleanup(Engine &engine);
	void onFrame(Engine &engine);
	void onStartFrame(Engine &engine);
	bool onEvent(Engine &engine, SDL_Event &event);

	/**
	 * @return the current instance.
	 *
	 * If there is no instance, it creates one. All actors call
	 *  this method when their constructors, so if you want to
	 *  extend it, you must do it before the creation of any actor.
	 */
	static ActorManager &getInstance();

	//////////////////
	//Event Handling//
	//////////////////

	/****************
	 * Frame Events *
	 ****************/
	void connectFrame(Actor &actor, mpFrameHandler method);
	void disconnectFrame(Actor &actor);
	void connectStartFrame(Actor &actor, mpFrameHandler method);
	void disconnectStartFrame(Actor &actor);
	void connectEndFrame(Actor &actor, mpFrameHandler method);
	void disconnectEndFrame(Actor &actor);

	/********************
	 * Collision Events *
	 ********************/
	void connectCollision(Actor &actor, mpCollisionHandler method);
	void disconnectCollision(Actor &actor);
protected:
	/**
	 * @brief The Constructor. You can't call it directly, but you can use it from a subclass.
	 *
	 * We recommend you subclass to have the constructor private too. It is necessary because
	 *  we can have only one instance of this. More instances may cause the system to
	 *  behave in an undefined way.
	 */
	ActorManager();
private:
	static ActorManager *instance;

	list<Actor*> actors;
	/******************
	 * Frame handlers *
	 ******************/
	map<Actor*, mpFrameHandler> frameHandlers;
	map<Actor*, mpFrameHandler> frameStartHandlers;
	map<Actor*, mpFrameHandler> frameEndHandlers;
	/**********************
	 * Collision handlers *
	 **********************/
	map<Actor*, mpCollisionHandler> collisionHandlers;
	/////////////////////////
	//Actor calling methods//
	/////////////////////////
	friend class Actor;
	void addActor(Actor &actor);
	void removeActor(Actor &actor);

};

} /* namespace wolf */
#endif /* ACTORMANAGER_HPP_ */
